package com.tsd.shiro.config;

import com.tsd.shiro.filter.ShiroAuthFilter;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.filter.InvalidRequestFilter;
import org.apache.shiro.web.filter.mgt.DefaultFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: ShiroConfig
 * @Description: TODO
 * @Author: Hillpool
 * @Date: 2023/6/20 9:46
 * @Version: 1.0
 */
@Configuration
public class ShiroConfig {

    @Resource
    private ModularRealmAuthenticator modularRealmAuthenticator;
    @Resource
    private BaseShiroConfig baseShiroConfig;


    /**
     * Realm管理，主要针对多realm 认证
     */
    @Bean
    public ModularRealmAuthorizer modularRealmAuthorizer() {
        return new ShiroModularRealmAuthorizer();
    }

    /**
     * 权限管理
     *
     * @param tokenRealm
     * @param sysUserRealm
     * @param ehCacheManager
     * @param sessionManager
     * @return
     */
    @Bean(value = "securityManager")
    public SessionsSecurityManager securityManager(@Qualifier("tokenRealm") Realm tokenRealm,
                                                   @Qualifier("sysUserRealm") Realm sysUserRealm,
                                                   @Qualifier("ehCacheManager") EhCacheManager ehCacheManager,
                                                   @Qualifier("sessionManager") SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //指定多 realm  先配置Authenticator-顺序不能相反
        securityManager.setAuthenticator(modularRealmAuthenticator);
        securityManager.setAuthorizer(modularRealmAuthorizer());
        List<Realm> list = Arrays.asList(tokenRealm, sysUserRealm);
        securityManager.setRealms(list);
        securityManager.setRememberMeManager(new CookieRememberMeManager());
        securityManager.setCacheManager(ehCacheManager);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    /**
     * 在此处配置过滤器链
     */
    @Bean(value = "authFilterChainDefinition")
    public ShiroFilterChainDefinition authFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = baseShiroConfig.getBaseAuthFilterChainDefinition();

        chainDefinition.addPathDefinition("/api/**", "auth");
        return chainDefinition;
    }

    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager,
                                                         @Qualifier("authFilterChainDefinition") ShiroFilterChainDefinition authFilterChainDefinition) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        shiroFilterFactoryBean.setLoginUrl("/admin/auth/401");
        shiroFilterFactoryBean.setSuccessUrl("/admin/auth/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/admin/auth/403");

        //自定义过滤器
        Map<String, Filter> filters = new HashMap<>();
        filters.put("auth", new ShiroAuthFilter());
        // 通过ResourceHandlerRegistry配置的静态资源中文名称无法访问原因
        InvalidRequestFilter filter = new InvalidRequestFilter();
        // 关闭校验
        filter.setBlockNonAscii(false);
        filters.put(DefaultFilter.invalidRequest.name(), filter);
        shiroFilterFactoryBean.setFilters(filters);

        shiroFilterFactoryBean.setFilterChainDefinitionMap(authFilterChainDefinition.getFilterChainMap());
        return shiroFilterFactoryBean;
    }
}
